package com.dianzhihan.net_demo.tcp;


import com.dianzhihan.net_demo.util.Log;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.Scanner;

// 长连接模式下，不能读取完一次请求就挂断电话
// 挂断电话的主动权交到客户端手中
// 客户端不挂电话，服务器就坚决不挂电话！！
// 表现在代码中，我们怎么就知道对方挂电话了？
// 我们是通过 InputStream 进行读取的
// 所以，当我们读到了 EOS，就代表，对方挂断电话了
// 区分：对方本次发送了个 0 个数据  n == 0
//      对方挂电话了： n == -1（只是一个信号，不是一个数据）
// EOS 表现到 scanner 中，就是 hasNextLine() 会返回 false
public class TranslateServerLongConnection {
    public static final int PORT = 8888;

    public static void main(String[] args) throws Exception {
        Log.println("启动长连接版本的 TCP 服务器");
        initMap();
        ServerSocket serverSocket = new ServerSocket(PORT);
        while (true) {
            // 接电话
            Log.println("等待对方来连接");
            Socket socket = serverSocket.accept();
            Log.println("有客户端连接上来了");

            // 对方信息：
            InetAddress inetAddress = socket.getInetAddress();  // ip
            Log.println("对方的 ip: " + inetAddress);
            int port = socket.getPort();    // port
            Log.println("对方的 port: " + port);
            SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress();    // ip + port
            Log.println("对方的 ip + port: " + remoteSocketAddress);

            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
            // 构造的过程只需要一次
            Scanner scanner = new Scanner(inputStream, "UTF-8");
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8");
            PrintWriter writer = new PrintWriter(outputStreamWriter);

            while (true) {
                Log.println("等待客户端 " + remoteSocketAddress + " 的请求 或者 挂电话");
                if (!scanner.hasNextLine()) {
                    Log.println("对方挂电话了");
                    // 代表 scanner 背后的 InputStream 遇到了 EOS(-1)
                    // 也就代表对方挂电话了
                    // 所以我们也可以退出了
                    break;  // 只会跳出内部循环
                }
                Log.println("对方来数据了");
                // 读取请求
                String request = scanner.nextLine();    // nextLine() 就会去掉换行符
                String engWord = request;
                Log.println("英文: " + engWord);

                // 翻译
                String chiWord = translate(engWord);
                Log.println("中文: " + chiWord);

                // 发送响应
                String response = chiWord;  // TODO: 响应的单词中是没有 \r\n

                Log.println("准备发送");
                writer.printf("%s\r\n", response);

                writer.flush();
                Log.println("发送成功");
            }

            // 挂掉电话
            socket.close();
            Log.println("挂断电话");
        }
//        serverSocket.close();
    }


    private static final HashMap<String, String> map = new HashMap<>();

    private static void initMap() {
        map.put("apple", "苹果");
        map.put("pear", "梨");
        map.put("orange", "橙子");
    }

    private static String translate(String engWord) {
        String chiWord = map.getOrDefault(engWord, "查无此单词");
        return chiWord;
    }
}
